﻿using System;
using System.Text;

namespace Xenta.Utils
{
    /// <summary>
    /// Represents the string chain base.
    /// </summary>
    public abstract class SChain
    {
        #region Fields

        private readonly StringBuilder _sb;

        #endregion

        #region Ctors

        protected SChain(string str = null)
        {
            _sb = new StringBuilder(str);
        }

        #endregion

        #region Properties

        protected StringBuilder Builder
        {
            get
            {
                return _sb;
            }
        }

        #endregion

        #region Methods

        public static implicit operator String(SChain str)
        {
            return str.ToString();
        }

        public override string ToString()
        {
            return Builder.ToString();
        }

        #endregion

    }

    /// <summary>
    /// Represents the error string builder.
    /// </summary>
    public sealed class Err : SChain
    {
        #region Ctors

        private Err() 
            : base("Error")
        {
        }

        #endregion

        #region Methods

        public static Err Of(string subject)
        {
            return new Err().Reason(subject);
        }

        public static Err Of(Type t)
        {
            return Of(t.Name);
        }

        public static Err Of<T>()
        {
            return Of(typeof(T));
        }

        public static Err Of(object obj)
        {
            return Of(obj.GetType());
        }

        public Err Reason(object subject)
        {
            if(subject == null) 
                return this;
            Builder.Append('.')
                .Append(subject);
            return this;
        }

        public Err No(string subject = null)
        {
            return Reason("No")
                .Reason(subject);
        }

        public Err NaN(string subject = null)
        {
            return Reason("NaN")
                .Reason(subject);
        }

        public Err NotValid(string subject = null)
        {
            return Reason("NotValid")
                .Reason(subject);
        }

        public Err NotAllowed(string subject = null)
        {
            return Reason("NotAllowed")
                .Reason(subject);
        }

        public Err NotFound(string subject = null)
        {
            return Reason("NotFound")
                .Reason(subject);
        }

        public Err NotSpecified(string subject = null)
        {
            return Reason("NotSpecified")
                .Reason(subject);
        }

        public Err NotInit(string subject = null)
        {
            return Reason("NotInitialized")
                .Reason(subject);
        }

        public Err NotConfigured(string subject = null)
        {
            return Reason("NotConfigured")
                .Reason(subject);
        }

        public Err NotAuthorized(string subject = null)
        {
            return Reason("NotAuthorized")
                .Reason(subject);
        }

        public Err NotAvailable(string subject = null)
        {
            return Reason("NotAvailable")
                .Reason(subject);
        }

        public Err NotPossible(string subject = null)
        {
            return Reason("NotPossible")
                .Reason(subject);
        }

        public Err NotApplicable(string subject = null)
        {
            return Reason("NotApplicable")
                .Reason(subject);
        }

        public Err NotIn(string subject = null)
        {
            return Reason("NotIn")
                .Reason(subject);
        }

        public Err Cannot(string act = null)
        {
            return Reason("Cannot")
                .Reason(act);
        }

        public Err ViolateOf(string subject = null)
        {
            return Reason("ViolateOf")
                .Reason(subject);
        }

        public Err OutOf(string subject = null)
        {
            return Reason("OutOf")
                .Reason(subject);
        }

        public Err Code(object code)
        {
            Reason("Code");
            Builder.Append('(')
                .Append(code)
                .Append(')');
            return this;
        }

        public Err Message(string message)
        {
            Builder.Append('(')
                .Append(message)
                .Append(')');
            return this;
        }

        public ApplicationException Ex(string source = null, 
            Exception innerException = null)
        {
            var ex = innerException != null 
                ? new ApplicationException(ToString(), innerException) 
                : new ApplicationException(ToString());
            if(!String.IsNullOrWhiteSpace(source))
                ex.Source = source;
            return ex;
        }

        #endregion
    }

    /// <summary>
    /// Represents the config string builder.
    /// </summary>
    public sealed class Par : SChain
    {
        #region Ctors

        private Par()
        {
        }

        #endregion

        #region Methods

        public static Par In(string section)
        {
            return new Par().Group(section);
        }

        public Par Of(string subject)
        {
            return Group(subject);
        }

        public Par Of(Type t)
        {
            return Of(t.Name);
        }

        public Par Of<T>()
        {
            return Of(typeof(T));
        }

        public Par Of(object obj)
        {
            return Of(obj.GetType());
        }

        public Par Group(object group)
        {
            Builder.Append(group)
                .Append('.');
            return this;
        }

        public Par Name(object param)
        {
            Builder.Append(param);
            return this;
        }

        #endregion
    }
}
